package p.ithorns.sample.websocket.debugger;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * GateDebugTcpMsgHandler
 *
 * @author HtL
 * @date 2024/10/10 13:37
 * @since 1.0.0
 */
@Slf4j
@ChannelHandler.Sharable
public class DebugTcpMsgHandler extends SimpleChannelInboundHandler<String> {


    public DebugTcpMsgHandler() {}


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 绑定WS-TCP
        Channel channel = ctx.channel();
        String tcpChId = channel.id().asShortText();
        log.info("[{}]=> TCP客户端建立连接", tcpChId);
        channel.writeAndFlush("Hello, Stranger!");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        String tcpId = getChannelId(ctx);

        // 连接后第一次消息，是否需要绑定
        if (!DebugWsTcpSupervise.hasTcpBind(tcpId)) {
            bindTcp2Ws(ctx.channel(),msg);
            return;
        }

        log.info("[{}]=> TCP客户端消息: {}", tcpId, msg);
        // 发到ws
        try {
            String wsId = DebugWsTcpSupervise.getWsId(tcpId);
            DebugWsTcpSupervise.sendToWs(wsId, msg);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 断线后需要销毁相关链接
        DebugWsTcpSupervise.removeChannel(channel);
        String tcpChId = channel.id().asShortText();
        DebugWsTcpSupervise.unbindWsTcp(tcpChId);
        log.warn("[{}]=> TCP客户端断开连接: {}", channel.id(), channel.remoteAddress());
    }

    private void bindTcp2Ws(Channel channel, String wsClientId) {
        // 检查是否开启WS客户端
        if (!DebugWsTcpSupervise.hasWsClient(wsClientId)) {
            throw new RuntimeException("未注册的客户端:" + wsClientId);
        }

        String tcpChId = channel.id().asShortText();
        String tcpKey = asTcpKey(wsClientId, tcpChId);
        boolean bind = DebugWsTcpSupervise.bindWsTcp(wsClientId, tcpChId);
        if (!bind) {
            throw new RuntimeException("已存在绑定的连接:" + tcpChId);
        }
        DebugWsTcpSupervise.register(tcpKey, channel);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel channel = ctx.channel();
        log.warn("[{}]=> TCP客户端出现异常: {}", channel, cause.getMessage());
        ctx.fireExceptionCaught(cause);
        // 出现异常断线处理
        channel.close().sync();
//        channelInactive(ctx);
    }

    private String getChannelId(ChannelHandlerContext ctx) {
        return ctx.channel().id().asShortText();
    }

    private String asTcpKey(String wsClientId, String channelId) {
        return wsClientId + ":" + channelId;
    }

}